/*
 *	SNiFF+ ParserAPI sample program
 *	
 *	This file contains an exaple for initializing
 *	the parser and managiong compile jobs.
 *	There are also some examples for using
 *	the semantic action routines of the API.
 */ 
 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "ParserInterface.h"

pi_data	data;

/*
 *	The following functions are wrappers around the
 *	semantic action functions filling the pi_data structure
 *	and performing the appropiate semantic action call.
 *
 */
void
comment_found(int from, int to)
{
	pi_reset(&data);
	data.from = from;
	data.to = to;
	pi_comment(&data);
}
void
macro_found(char *name, int from)
{
	pi_reset(&data);
	data.name = name;
	data.from = from;
	data.to = from + 10;
	pi_macro(&data);
}
void
function_found(char *name, char *type, int from, char *classname)
{
	pi_reset(&data);
	data.name = name;
	data.from = from;
	data.to = from + 5;
	data.from2 = from + 10;
	data.to2 = from + 20;
	data.flags = PI_DEFINITION;
	data.type = type;
	if(classname)
		data.classname = classname;
	pi_function(&data);
}
void 
include_found(char *name,int from,int to, int std )
{
	pi_reset(&data);
	data.name	=	name;
	data.from	=	from;
	data.to		=	to;
	data.flags	=	(std)?PI_STDINCL:0;
	
	pi_include(&data);
} 
void
userdef_found(char *name,char *type,int from, int to )
{
	pi_reset(&data);
	data.name	=	name;
	data.type	=	type;
	data.from	=	from;
	data.to		=	to;
	
	pi_userdef(&data);
}
void
function_decl_found(char *name, char *type, int from, int vis)
{
	pi_reset(&data);
	data.name = name;
	data.from = from;
	data.to = from + 5;
	data.from2 = from + 10;
	data.to2 = from + 20;
	data.flags = PI_DECLARATION | vis;
	data.type = type;
	pi_function(&data);
}
void
parameter_found(char *name, char *type)
{
	pi_reset(&data);
	data.name = name;
	data.type = type;
	pi_parameter(&data);
}
pi_id 
enum_found(char *name, char *type, int from, int to, pi_id id)
{
	pi_reset(&data);
	data.name = name;
	data.type = type;
	data.from = from;
	data.to   = to;
	data.related = id;
	data.flags = PI_PUBLIC;
return	pi_enum(&data);
}
void
enum_item(char *name,int from, int to, pi_id id )
{
	pi_reset(&data);
	data.name = name;
	data.from = from;
	data.to   = to;
	data.related = id;
	pi_enum_item(&data);
}
 
pi_id
start_class(char *name,int from)
{
	pi_reset(&data);
	data.name = name;
	data.from = from;
	data.to = from + 5;
	data.flags = PI_CLASS;
return	pi_start_class(&data);
}
void
end_class(int from)
{
	pi_reset(&data);
	data.from = from+20;
	data.to = from + 120;
	pi_end_class(&data);
	
}
void
variable_found(char *name, char *type, int flags, int from)
{
	pi_reset(&data);
	data.name = name;
	data.type = type;
	data.from = from;
	data.to = from + 5;
	data.flags = flags;
	pi_variable(&data);
}
void
reference_found(char *name, int atPosition, int what)
{
	pi_reset(&data);
	data.name = name;
	data.from = atPosition;
	data.flags = what;
	pi_reference(&data);

}

/*
 *	This function shows some examples of calling
 *	semantic action functions.
 */
void
parse(pi_job *job)
{
	pi_id scope;
	fprintf(stderr,"File to parse: \"%s\"\n",job->source_file_name);	

	/*
	 *	Comments
	 */
	comment_found(10,100);
	comment_found(200,250);
	/*
	 *	Macro definitions
	 *	C++ example: #define foo_macro 1
	 *				 #define bar_macro 2
	 */
	macro_found("foo_macro",300);
	macro_found("bar_macro",350);
	
	/*
	 * Include directive
	 * C++ example: #include <standart.h>
	 * 				#include "userdef.h"
	 *
	 */
	
	include_found( "standart.h"	, 110 ,120, 1 );
	include_found( "userdef.h"	, 121 ,130, 0 );
	
	
	/*
	 *	Global function definition with
	 *	three formal parameters.
	 *	C++ example: foo_function(char *p1, int p2, long p3) { ... }
	 */
	function_found("foo_function","int",400,0);
	parameter_found("p1","char *");
	parameter_found("p2","int");
	parameter_found("p3","long");
	/*
	 *	Reference to a macro and a variable.
	 *  This two functions
	 *	define references to the macro "foo_macro" and
	 *  the variable "foovar" by the function "foo_function".
	 *	C++ example: foo_function(char *p1, int p2, long p3)
	 *				 {
	 *					foovar = bar_macro;
	 *				 }
	 */  
	reference_found("foo_macro",50, PI_MACRO);
	reference_found("foovar",41, PI_VARIABLE | PI_WRITEACCESS);
	
	/*
	 *	Member function definition with
	 *	one formal parameter.
	 *	C++ example: bar_class::bar_function(int p1) { ... }
	 */	
	function_found("bar_function","char *",450,"bar_class");
	parameter_found("p1","int");

	/*
	 *	Class declaration
	 *	C++ example:	class bar_class
	 *					{
	 *					private:
	 *						static int	inst_foovar1;
	 *						int		*inst_foovar2;
	 *					protected:
	 *						char	*bar_function(char);
	 *						float	inst_foovar4;
	 *					public:
	 *						char	*bar_function(int);
	 *						long	inst_foovar3;
	 *					};
	 */						
	scope = start_class("bar_class",500);
	function_decl_found("bar_function","char *",550,PI_PUBLIC);
	parameter_found("p1","int");
	function_decl_found("bar_function","char *",570,PI_PROTECTED);
	comment_found(560,565);
	parameter_found("p1","char");
	userdef_found( "int operator()(bar_class&)", "overloaded Operator",570,580 );
	userdef_found( "int (PTR2MF::&bar_class)(int&)","pointer to function",590,600);
	variable_found("inst_foovar1", "int",PI_STATIC, 810);
	variable_found("inst_foovar2", "int*",PI_PRIVATE, 820);
	variable_found("inst_foovar3", "long",PI_PUBLIC, 840);
	variable_found("inst_foovar4", "float",PI_PROTECTED, 850);
	scope = enum_found("ENUM1","enum",860,873,scope );
	enum_item( "ITEM1",862,863,scope);
	enum_item( "ITEM2",865,867,scope);
	enum_item( "ITEM3",869,871,scope);
	end_class(500);

	/*
	 *	Global variable definition
	 *	C++ example:  char *foovar;
	 */
	variable_found("foovar", "char *",0, 860);
	
	/*
	 *	Member function definition with
	 *	one formal parameter.
	 *	C++ example: bar_class::bar_function(char *p1) { ... }
	 */	
	function_found("bar_function","char *",450,"bar_class");
	parameter_found("p1","char");
	
	/*
	 * Userdefined Symbol
	 * C++ example:	typedef int(foo)(int i); 	// declaration of a function ointer
	 *				int operator()(int&);		// overloaded Functioncall operator 
	 *											// within int
	 */
	 
	 userdef_found( "typedef int(foo)(int i)","pointer to function",351,375 );
	 userdef_found( "int operator()(int&)", "overloaded Operator",376,397 );
	 
	 pi_error_msg( "E Bug in file " );
	 pi_error_msg( "W Bug in file " );
	 pi_error_msg( "Bug in file " );
	
}
/*
 *	Get basename of a full pathname

char *
BaseName(char *path)
{
	char *basename;
	if((basename = strrchr(path,'/')) == NULL)
		return path;
	else
		return ++basename;
}
*/

/*
 *	Example for setting up the connection to SNiFF+ core
 *	process and looping over the compile jobs.
 */
void
main(int argc, char *argv[])
{
	pi_job	*job;	
	/*	char 	*parserName = system_RemExecutableExt(system_BaseName(argv[0])); */
	char 	*parserName = (char *)system_RemExecutableExt(system_BaseName(argv[0]));

	fprintf(stderr,"Init parser \"%s\"\n", parserName);
	
	if(pi_init(0,parserName))
		exit(1);

	while ((job = pi_getjob()))
	{
		parse(job);
		pi_endjob(job);
	}
	exit(0);
}
